import tkinter as tk
from tkinter import ttk
from page import StartPage
from PIL import ImageTk, Image
from page.Config import Config
from tkinter import filedialog, messagebox
import random
import pygame

# 主界面
class UsePage(tk.Frame):
    
    number = 0  #抽取数量
    awardIndex = 0  #抽取项索引
    speed =  Config().data['speed'] # 抽取速度
    awardlist = Config.toJson("./data/awardlist.json")
    userList =  Config.toJson("./data/userlist.json")
    gameStatus = 0 # 未开始
    winList = {}    # 中奖名单
    scrollIndex = 0 # 滚动索引
    winCount = 0 #抽取次数
    
    # 中奖动画
    winActiveIndex = 0

    # 抽取项
    winSelect = ''  #抽取项名称
    winOption = [item['winPro'] for item in awardlist]

    # 设置滚动特效属性
    setValue = {
        "numberFontSize":64,
        "numberFontColor":"#ffffff",
        "xy":(300,int(Config().data['screenHeight'] * 0.68)),    # x未用
        "text_id":""
        }
    
    # 设置中奖姓名属性
    setNameValue = {
        "numberFontSize":94,
        "numberFontColor":"#ffffff",
        "xy":(200,int(Config().data['screenHeight'] * 0.68 - 120))  # x未用
    }

    # 设置中奖列表属性
    setListValue = {
        "numberFontSize":18,
        "numberFontColor":"#ffffff",
        "xy":(int(Config().data['screenWidth'] - 30),20),
        "index":0,
        "lineHight":30,
        "ids":{}
    }

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        
    def show_image_with_size(self,image_path, width=None, height=None):
        # 使用Pillow打开并调整图片
        original_img = Image.open(image_path)
        
        # 根据参数调整尺寸（保持宽高比）
        if width or height:
            w, h = original_img.size
            if width and height:  # 同时指定宽高
                size = (width, height)
            elif width:  # 仅指定宽度
                ratio = width / float(w)
                size = (width, int(h * ratio))
            else:  # 仅指定高度
                ratio = height / float(h)
                size = (int(w * ratio), height)
            resized_img = original_img.resize(size, Image.LANCZOS)
        else:
            resized_img = original_img

        return resized_img    
    
    def minWindow(self,controller):
        config = Config()
        controller.geometry(f"800x600+{int((config.data['screenWidth']-800)/2)}+{int((config.data['screenHeight']-600)/2)}")
        controller.show_frame(StartPage.StartPage)

    # 初始化
    def document(self):
        config = Config()
        # 加载图片
        if config.data['backgroud']:
            bg_img = ImageTk.PhotoImage(self.show_image_with_size(rf"{Config.resource_path(config.data['backgroudSrc'])}",config.data['screenWidth']))
            # 在Frame中创建Label作为背景
            self.bg_canvas = tk.Canvas(self, width=config.data['screenWidth'], height=config.data['screenHeight'],bg="white", highlightthickness=0)
            self.bg_canvas.place(x=0, y=0, relwidth=1, relheight=1)
            self.bg_canvas.create_image(
                0, 0,
                image=bg_img,
                anchor='nw',
                tags="bg"
            )
            self.bg_canvas.bg = bg_img
        
        # 画布绑定窗口缩放
        self.bg_canvas.bind("<Configure>", self.update_text_position)

        # 设置抽奖奖项
        if self.awardlist:
            self.winCombobox = ttk.Combobox(self, values=self.winOption)
            self.winCombobox.current(0)
            self.number = self.awardlist[0]['number']
            self.winSelect = self.awardlist[0]['winPro']
            self.winCombobox['state'] = 'readonly'
            tk.Label(self,text="抽奖奖项").place(x=15,y=config.data['screenHeight']-240)
            self.winCombobox.place(x=80,y=config.data['screenHeight']-240)
            # 绑定事件
            self.winCombobox.bind("<<ComboboxSelected>>", self.selectWin)
        else:
            messagebox.showerror("错误","当前未导入奖品名单！")

        # 设置抽奖速度
        tk.Label(self,text="抽奖速度").place(x=15,y=config.data['screenHeight']-200)
        self.speed_spinbox = ttk.Spinbox(self, width=10,from_=1, to=100,command=self.speedChange)
        self.speed_spinbox.set(self.speed)
        self.speed_spinbox.bind("<FocusOut>", lambda e: self.speedChange())  # 焦点离开时检查输入
        self.speed_spinbox.place(x=80,y=config.data['screenHeight']-200)

        # 显示抽奖名额 state='readonly'
        tk.Label(self,text="抽奖数量").place(x=15,y=config.data['screenHeight']-160)
        self.number_entry = tk.Entry(self, width=10)
        self.updateNumberEntry()
        self.number_entry.place(x=80,y=config.data['screenHeight']-160)

        # 返回按钮
        btn1 = tk.Button(self, text="返回",command=lambda: self.minWindow(self.controller))
        btn1.place(x=15, y=config.data['screenHeight']-120)

        # 抽奖音乐

        # 抽奖开始按钮
        self.startBtn = tk.Button(self, text="开始",command=lambda: self.startGame(),width=15,bg="#FFA500",fg="white")
        self.startBtn.place(x=config.data['screenWidth']/2-120, y=config.data['screenHeight']-240)

        # 抽奖抽中按钮
        self.pauseBtn = tk.Button(self, text="停止",command=lambda: self.pauseGame(),width=15,bg="#FFA500",fg="white")
        self.pauseBtn.place(x=config.data['screenWidth']/2+30, y=config.data['screenHeight']-240)

        # 展示抽奖信息
        # 1.抽奖时变动的编号
        # 2.抽奖中后显示的姓名以及编号
        # 3.中奖列表 通过新增画布来模拟背景,同时显示中奖列表
        # self.list_canvas = tk.Canvas(self,bg="white",width=config.data['screenWidth'],height=config.data['screenHeight'], highlightthickness=0)
        # self.list_canvas.place(relx=1.0, rely=0,anchor=tk.NE, relwidth=0.3, relheight=0.3)
        # # 增加滚动条
        # self.scrollbar = tk.Scrollbar(self, orient="vertical", command=self.list_canvas.yview)
        # self.list_canvas.configure(yscrollcommand=self.scrollbar.set)
        # self.scrollbar.pack(side="right", fill="y")
        # # 3.1 中奖背景图
        # # 在Frame中创建Label作为背景
        # self.list_canvas.create_image(
        #     -config.data['screenWidth']*0.7, 0,
        #     image=bg_img,
        #     anchor='nw',
        #     tags="listBg"
        # )
        # self.list_canvas.listBg = bg_img
        # for i in range(100):
        #     self.list_canvas.create_text(
        #             config.data['screenWidth']*0.3 - 30, i*20,
        #             text="123456789",
        #             font=("Arial", 18),
        #             fill="#000000",
        #             anchor=tk.NE,
        #     )
        
        pass
    
    # 开始抽奖
    def startGame(self):
        if self.userList:
            # 检查抽取状态,以及当前奖项是否抽取过
            if self.gameStatus == 0 and not (self.awardIndex in self.winList) and self.number > 0:
                # 修改抽奖状态
                self.gameStatus = 1
                # 锁定可修改内容
                self.winCombobox['state'] = "disabled"  #锁定奖项
                self.speed_spinbox.config(state="disabled") #锁定抽奖速度
                self.startBtn.config(state="disabled")  #锁定开始按钮
                # 删除名称显示  该处为抽奖后显示
                self.bg_canvas.delete("name")
                # 开始滚动编号
                self.scrollActive()
            else:
                messagebox.showerror("错误","当前奖项已抽完！") 
        else:
            messagebox.showerror("错误","当前未导入抽奖名单！")   
        pass

    # 滚动效果
    def scrollActive(self):
        self.scrollIndex = (self.scrollIndex + 1) % len(self.userList)
        text = self.userList[self.scrollIndex]['number'] if self.userList[self.scrollIndex]['number'] else self.userList[0]['number']
        # 暂停时将文字替换成中奖人员
        if self.gameStatus == 0:
            text = self.winList[self.awardIndex][0]['number']
        if self.setValue['text_id']:
            self.bg_canvas.delete(self.setValue['text_id'])
        self.setValue['text_id'] = self.bg_canvas.create_text(
            self.bg_canvas.winfo_width() / 2, self.setValue['xy'][1],
            text=text,
            font=("Arial", self.setValue['numberFontSize']),
            fill=self.setValue['numberFontColor'],
            anchor=tk.CENTER,
        )
        if self.gameStatus == 1:  
            self.after(int(1000/self.speed),self.scrollActive)
        else:   #结束动画时归0
            self.scrollIndex = 0    

    # 停止抽奖 / 选择抽中的人
    def pauseGame(self):
        # 解除锁定
        self.winCombobox['state'] = "readonly"  
        self.speed_spinbox.config(state="normal") 
        self.startBtn.config(state="normal")  
        # 删除之前列表中奖人员
        self.bg_canvas.delete("list")
        # 次数重置
        self.setListValue['index'] = 0 
        # 计算中奖人员列表
        count = self.number #当前抽取数量
        # 1.优先锁定奖项人员
        winIndexs = UsePage.find_indices_by_value(self.userList,"winPro",self.winSelect)
        # 避免内定人员数量超过可中奖人员数量
        if count < len(winIndexs):
            winIndexs = winIndexs[:count]
        self.winList[self.awardIndex] = [self.userList[i] for i in winIndexs]  if winIndexs else []
        # 删除中奖者
        for index in sorted(winIndexs[::-1], reverse=True):
            del self.userList[index]
        # 2.如果还有名额 计算抽奖人员列表（根据设置的几率） 随机获取中奖人员并加入上列表
        if count > len(winIndexs):  
            cpUserList = self.computerList()
            # 生成随机中奖人员下标
            for i in range(count - len(winIndexs)):
                random_number = random.randint(0, len(cpUserList)-1)
                self.winList[self.awardIndex].append(self.userList[UsePage.find_indices_by_value(self.userList,'number',cpUserList[random_number])[0]])
                #删除抽奖列表已抽取人员
                cpUserList = [x for x in cpUserList if x != cpUserList[random_number]]
        # 加上中奖信息
        for i in range(len(self.winList[self.awardIndex])):
            self.winList[self.awardIndex][i]['winPro'] = self.awardlist[self.awardIndex]["winPro"]
            self.winList[self.awardIndex][i]['winTitle'] = self.awardlist[self.awardIndex]["winTitle"]  
        # 进行中奖人员动画
        self.gameStatus = 0 #关闭抽取动画
        self.winActive()

        # 将当前奖项数量设置为0
        self.awardlist[self.awardIndex]['number'] = 0
        self.number = 0
        self.updateNumberEntry()

        # 抽取次数+1
        self.winCount += 1
        # 全部奖抽取完毕，保存数据
        if self.winCount == len(self.awardlist):
            self.exportWinList()

        # 更新抽取奖项列表 -- 暂时不启用
        # self.winOption.remove(self.winSelect)
        pass

    # 生成当前能中奖的人员名单（加上设置的概率)
    def computerList(self):
        data = []
        for val in self.userList:
            for i in range(val['winRate']):
                data.append(val['number'])
        random.shuffle(data)    
        return data
    
    # 中奖动画
    def winActive(self):
        if self.winActiveIndex < len(self.winList[self.awardIndex]):
            # 1.显示编号
            if self.setValue['text_id']:
                self.bg_canvas.delete(self.setValue['text_id'])
            self.setValue['text_id'] = self.bg_canvas.create_text(
                self.bg_canvas.winfo_width() / 2, self.setValue['xy'][1],
                text=self.winList[self.awardIndex][self.winActiveIndex]['number'],
                font=("Arial", self.setValue['numberFontSize']),
                fill=self.setValue['numberFontColor'],
                anchor=tk.CENTER,
            )
            # 2.显示姓名
            self.bg_canvas.delete("name")
            self.bg_canvas.create_text(
                self.bg_canvas.winfo_width() / 2, self.setNameValue['xy'][1],
                text=self.winList[self.awardIndex][self.winActiveIndex]['name'],
                font=("Arial", self.setNameValue['numberFontSize']),
                fill=self.setNameValue['numberFontColor'],
                anchor=tk.CENTER,
                tags="name"
            )

            # 3.显示中奖列表
            self.activelist()
            # 递归动画
            self.winActiveIndex += 1
            # self.after(int(1000/self.speed),self.winActive)
            self.after(300,self.winActive)
        else:
            self.winActiveIndex = 0
        pass

    # 专门显示中奖列表
    def activelist(self):
        if self.setListValue['index'] < 10:
            text = f"{int(self.setListValue['index']+1)}.{self.winList[self.awardIndex][self.winActiveIndex]['winPro']} {self.winList[self.awardIndex][self.winActiveIndex]['number']} {self.winList[self.awardIndex][self.winActiveIndex]['position']}-{self.winList[self.awardIndex][self.winActiveIndex]['name']} {self.awardlist[self.awardIndex]['winTitle']}"
            self.setListValue['ids'][self.setListValue['index']] = self.bg_canvas.create_text(
                self.setListValue['xy'][0], self.setListValue['xy'][1]+(self.setListValue['index']*self.setListValue['lineHight']),
                text=text,
                font=("Arial", self.setListValue['numberFontSize']),
                fill=self.setListValue['numberFontColor'],
                anchor=tk.NE,
                tags="list"
            )
        else:
            # 删除当前显示的列表
            self.bg_canvas.delete("list")
            # 当前显示的循环系数    
            index = self.setListValue['index'] - 9    
            for i in range(10):
                text = f"{int(index+i+1)}.{self.winList[self.awardIndex][index+i]['winPro']} {self.winList[self.awardIndex][index+i]['number']} {self.winList[self.awardIndex][index+i]['position']}-{self.winList[self.awardIndex][index+i]['name']} {self.awardlist[self.awardIndex]['winTitle']}"
                self.setListValue['ids'][index+i] = self.bg_canvas.create_text(
                    self.setListValue['xy'][0], self.setListValue['xy'][1]+(i*self.setListValue['lineHight']),
                    text=text,
                    font=("Arial", self.setListValue['numberFontSize']),
                    fill=self.setListValue['numberFontColor'],
                    anchor=tk.NE,
                    tags="list"
                )

        self.setListValue['index'] += 1    
        pass

    # 滚动显示中奖人员

    # 选择抽奖奖项
    def selectWin(self,event):
        # 更新当前奖项
        self.winSelect = self.winCombobox.get()
        self.awardIndex = UsePage.find_index_2d(self.awardlist,'winPro',self.winSelect)
        self.number = self.awardlist[self.awardIndex]['number']
        self.updateNumberEntry()
        pass      

    # 抽奖速度 记录到config
    def speedChange(self):
        config = Config()
        self.speed = int(self.speed_spinbox.get())
        config.data['speed'] = self.speed 
        config.dump()
        pass

    # 更新抽奖数量显示
    def updateNumberEntry(self):
        # 更新抽奖数量
        self.number_entry.config(state='normal')
        self.number_entry.delete(0,tk.END)
        self.number_entry.insert(0,self.number)
        self.number_entry.config(state='readonly')
        pass
    
    # 遍历数组取键名
    def find_index_2d(lst,key, target):
        for i, row in enumerate(lst):
            if target in row[key]:
                return i  # 返回 行索引
        return None  

    # 遍历数组取键名（所有)
    def find_indices_by_value(data,key, target_value):
        """返回所有匹配target_value的字典索引列表"""
        return [i for i, item in enumerate(data) if item[key] == target_value]

    # 导出中奖名单
    def exportWinList(self):
        if len(self.winList) > 0:
            # 将抽奖信息保存json
            data = []
            for i in self.winList:
                for v in self.winList[i]:
                    data.append(v)
            Config.wWinList(data)
        pass

    # 窗口缩放监听
    def update_text_position(self, event=None):
        """窗口大小变化时重新居中文本"""
        if self.setValue['text_id']:
            new_x = self.bg_canvas.winfo_width() / 2
            new_y = self.bg_canvas.winfo_height() / 2
            self.bg_canvas.coords(self.setValue['text_id'], new_x, new_y)

    # 进入页面
    def on_enter(self):
        #创建页面内容
        self.document()
        # 播放音乐
        pygame.mixer.init()
        pygame.mixer.music.load(Config().data['music'])
        pygame.mixer.music.play(-1)
        pass

    # 离开页面
    def on_leave(self):
        self.exportWinList()
        pygame.mixer.music.pause()
        pass 